﻿using Infrastructure.ElasticSearch.Enums;
using Nest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Infrastructure.ElasticSearch.Nests
{
    public class ElasticSearchItem<T> where T : class
    {
        private Field _field;
        private string _path;
        private QueryPositionEnum _pos;
        private QueryPositionEnum _nestPos;
        private QueryOperator _opera;
        private string _orginFieldName; //原始字段名

        public string Path { get { return _path; } }
        public QueryPositionEnum Pos { get { return _pos; } }
        public QueryPositionEnum NestPos { get { return _nestPos; } }

        public QueryOperator Operator { get { return _opera; } }

        private List<string> _itemListVal;

        public string OrginFieldName { get { return _orginFieldName; } }

        public Field Field { get { return _field; } protected set { _field = value; } }

        public List<string> ItemListVal { get { return _itemListVal; } }

        public string SearchFieldName { get; set; }

        protected string SearchFieldPre { get { return (string.IsNullOrWhiteSpace(_path) ? string.Empty : $"{_path}."); } }

        public ElasticSearchItem(Expression<Func<T, object>> field,
            QueryOperator opera = QueryOperator.Include,
            QueryPositionEnum position = QueryPositionEnum.Must,
            string path = "",
            QueryPositionEnum nestPosition = QueryPositionEnum.None)
        {
            _opera = opera;

            _pos = position;
            _path = path;

            if (string.IsNullOrEmpty(path))
            {
                _nestPos = QueryPositionEnum.None;
            }
            else
            {
                _nestPos = nestPosition == QueryPositionEnum.None ? QueryPositionEnum.Must : nestPosition;
            }

            MemberExpression member = field.Body as MemberExpression;
            _orginFieldName = member.Member.Name;
            SearchFieldName = _orginFieldName;

            _field = new Field(_orginFieldName);
        }


        public virtual QueryContainerDescriptor<T> Search()
        {
            var request = new QueryContainerDescriptor<T>();
            switch (this.Operator)
            {
                case QueryOperator.Equal:
                case QueryOperator.NotEqual:
                    if (_itemListVal.Count > 1)
                    {
                        request.Terms(m => m.Field(_field).Terms(_itemListVal));
                    }
                    else
                    {
                        request.Match(m => m.Field(_field).Query(_itemListVal.First()));
                    }
                    break;
                case QueryOperator.Like:
                    request.MatchPhrase(m => m.Field(_field).Query(_itemListVal.First()));
                    break;
                default:
                    request.Terms(m => m.Field(_field).Terms(_itemListVal));
                    break;
            }
            return request;
        }

        public virtual void SetItemVal(List<string> val)
        {
            if (val == null) return;
            _itemListVal = val;
        }
    }
}
